package com.sqfw.project.utils.bssSign;

import com.alibaba.fastjson2.JSONObject;
import com.sqfw.project.system.domain.SysBssSign;
import com.sqfw.project.system.service.ISysBssSignService;
import com.sqfw.project.utils.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class BssSignUtils {

    @Value("${bssSign.apiUrl}")
    private String apiUrl;

    @Value("${bssSign.certAlias}")
    private String certAlias;

    /** 签名url */
    private static final String signDataUrl = "/api/svs/bss/signData";
    /** 验证签名url */
    private static final String verifySignedDataUrl = "/api/svs/bss/verifySignedData";

    @Autowired
    private ISysBssSignService sysBssSignService;

    /**
     * 第一次签名
     * @param correlationId 关联id
     * @param originData 签名数据
     * @param dataType 数据类型
     * @return
     * */
    /** 签名 */
    public boolean signData(String correlationId, String originData, String dataType) {
        SysBssSign queryBssSign = new SysBssSign();
        queryBssSign.setCorrelationId(correlationId);
        queryBssSign.setDataType(dataType);
        List<SysBssSign> signs = sysBssSignService.selectSysBssSignList(queryBssSign);
        if (!CollectionUtils.isEmpty(signs)) {
            log.info("已经签名了：{}", correlationId);
            return true;
        }
        String b64OriginData = Base64.getEncoder().encodeToString(originData.getBytes());
        Map<String, String> params = new HashMap<>(6);
        params.put("b64OriginData", b64OriginData);
        params.put("certAlias", certAlias);
        log.info("接口签名请求参数params： " + params.toString());
        log.info("接口签名请求url： " + apiUrl + signDataUrl);
        // 调用接口
        String result = HttpClientUtils.postJson(apiUrl + signDataUrl, params);
        log.info("接口签名请求接口返回result: " + result);
        if (StringUtils.isBlank(result)) {
            log.info("接口请求签名接口失败");
            return false;
        }else {
            JSONObject resJson = JSONObject.parseObject(result);
            // 成功
            if ("0".equals(resJson.getString("errorCode"))) {
                String b64SignedData = resJson.getString("b64SignedData");
                String b64Cert = resJson.getString("b64Cert");
                SysBssSign sysBssSign = new SysBssSign(correlationId, dataType,
                        originData, b64OriginData, certAlias, b64SignedData, b64Cert);
                sysBssSignService.insertSysBssSign(sysBssSign);
                return true;
            }else {
                log.error("接口签名获取失败：" + resJson.getString("errorCode"));
            }
            return false;
        }
    }

    /**
     * 验证签名
     * @param correlationId 关联id
     * @param originData 签名的数据
     * @param dataType 数据类型（根据关联id+数据类型，查询出唯一的一条数据）
     * @return
     * */
    /** 验签 */
    public boolean verifySignedData(String correlationId, String originData, String dataType) {
        SysBssSign sysBssSign = new SysBssSign();
        sysBssSign.setCorrelationId(correlationId);
        sysBssSign.setDataType(dataType);
        List<SysBssSign> signs = sysBssSignService.selectSysBssSignList(sysBssSign);
        if (!CollectionUtils.isEmpty(signs)) {
            SysBssSign bssSign = signs.get(0);
            if (StringUtils.isNotBlank(bssSign.getB64Cert())) {
                String b64OriginData = Base64.getEncoder().encodeToString(originData.getBytes());
                // 调用接口
                Map<String, String> params = new HashMap<>(10);
                params.put("b64OriginData", b64OriginData);
                params.put("b64SignedData", bssSign.getB64SignedData());
                params.put("b64Cert", bssSign.getB64Cert());
                log.info("接口验证签名请求参数params： " + params.toString());
                log.info("接口验证签名请求url： " + apiUrl + verifySignedDataUrl);
                // 调用接口
                String result = HttpClientUtils.postJson(apiUrl + verifySignedDataUrl, params);
                log.info("接口验证签名请求接口返回result: " + result);
                if (StringUtils.isBlank(result)) {
                    log.info("接口验证签名请求接口返回失败");
                    return false;
                }else {
                    JSONObject resJson = JSONObject.parseObject(result);
                    // 成功
                    if (!"0".equals(resJson.getString("errorCode"))) {
                        sysBssSignService.updateById(bssSign.getId());
                        return true;
                    }else {
                        return false;
                    }
                }
            }
            return false;
        }else {
            log.error("没有接口签名信息");
            return false;
        }
    }


    /**
     * 第二次签名(签名的数据有修改，进行第二次签名)
     * @param correlationId 关联id
     * @param originData 签名数据，（修改后的数据）
     * @param dataType 数据类型
     * @return
     * */
    public boolean signUpdateData(String correlationId, String originData, String dataType) {
        SysBssSign queryBssSign = new SysBssSign();
        queryBssSign.setCorrelationId(correlationId);
        queryBssSign.setDataType(dataType);
        List<SysBssSign> signs = sysBssSignService.selectSysBssSignList(queryBssSign);
        if (CollectionUtils.isEmpty(signs)) {
            log.info("没有签名过：{}", correlationId);
            return false;
        }
        SysBssSign bssSign = signs.get(0);
        if (bssSign.getOriginData().equals(originData)) {
            log.info("没有修改签名数据：{}", originData);
            return true;
        }
        String b64OriginData = Base64.getEncoder().encodeToString(originData.getBytes());
        Map<String, String> params = new HashMap<>(6);
        params.put("b64OriginData", b64OriginData);
        params.put("certAlias", certAlias);
        log.info("第二次接口签名请求参数params： " + params.toString());
        log.info("第二次接口签名请求url： " + apiUrl + signDataUrl);
        // 调用接口
        String result = HttpClientUtils.postJson(apiUrl + signDataUrl, params);
        log.info("第二次接口签名请求接口返回result: " + result);
        if (StringUtils.isBlank(result)) {
            log.info("第二次接口请求签名接口失败");
            return false;
        }else {
            JSONObject resJson = JSONObject.parseObject(result);
            // 成功
            if ("0".equals(resJson.getString("errorCode"))) {
                String b64SignedData = resJson.getString("b64SignedData");
                String b64Cert = resJson.getString("b64Cert");
                SysBssSign sysBssSign = new SysBssSign(correlationId, dataType,
                        originData, b64OriginData, certAlias, b64SignedData, b64Cert);
                sysBssSign.setId(bssSign.getId());
                sysBssSign.setIsUpdate(0);
                sysBssSignService.updateSysBssSign(sysBssSign);
                return true;
            }else {
                log.error("第二次接口签名获取失败：" + resJson.getString("errorCode"));
            }
            return false;
        }
    }



}
